﻿#include "datafactory.h"
#include "../include/taskthread.h"

DataFactory::DataFactory(QObject *parent) : QThread(parent), circularQueue(MAX_SPACE)
{
    initSomeValues();
    //串口
    PortSettings settings = {BAUD115200, DATA_8, PAR_NONE, STOP_1, FLOW_OFF, 10};
    serialPort = new QextSerialPort("COM1", settings);
    connect(serialPort, SIGNAL(readyRead()), SLOT(onSerialReadyRead())); //serial data is coming
    tcpSocket = new QTcpSocket(this);
    connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(onNetReadyRead()));
    sqlthread = new SQLThread();
    //启动时间总线
    timeBus.start();
    //启动数据库执行线程
    sqlthread->start();
    // start(); //mainwindow run the cmd
    connect(&timeBus, SIGNAL(checkSim()), this, SLOT(checkSimOnlineState())); //每一个小时执行一次检测
}
void DataFactory::sendMsgAT()
{
    if(serialPort->isOpen())
    {
        QByteArray ba = AT.toLatin1();
        const char *cstr = ba.data();
        serialPort->write(cstr);
    }
}
void DataFactory::sendMsgCMGF()
{
    if(serialPort->isOpen())
    {
        QByteArray ba = TEXT.toLatin1();
        const char *cstr = ba.data();
        serialPort->write(cstr);
    }
}
void DataFactory:: sendMsgCNMI()
{
    if(serialPort->isOpen())
    {
        QByteArray ba = ECHO.toLatin1();
        const char *cstr = ba.data();
        serialPort->write(cstr);
    }
}
void DataFactory:: sendMsgRMALL()
{
    if(serialPort->isOpen())
    {
        QByteArray ba = DELALL.toLatin1();
        const char *cstr = ba.data();
        serialPort->write(cstr);
    }
}
void DataFactory:: sendMsgReadN(int n)
{
    if(serialPort->isOpen())
    {
        QByteArray ba = READ(n).toLatin1();
        const char *cstr = ba.data();
        serialPort->write(cstr);
        //qDebug() << "Send to Serial" << ba.data() << endl;
    }
}
/*
global.h
#define AT QString("AT\r\n")
#define TEXT QString("AT+CMGF=1\r\n")
#define ECHO QString("AT+CNMI=2,1\r\n")
#define READ(n) (QString("AT+CMGR=")+QString::number(n)+ QString("\r\n"))
#define DELONE(n)   (QString("AT+CMGD=")+QString::number(n)+ QString("\r\n"))
#define DELALL  QString("AT+CMGDA=\"DEL ALL\"\r\n")
#define LISTALL QString("AT+CMGL=\"ALL\"\r\n")

*/
void DataFactory::checkSimOnlineState()
{
    //可通过timeBus.setFistCheckSim()更改状态
    sendMsgAT();
    QTimer::singleShot(10 * 1000, this, SLOT(sendMsgCMGF()));
    QTimer::singleShot(20 * 1000, this, SLOT(sendMsgCNMI()));
}
/*
bool DataFactory::checkSmsVecIsEmpty()  //timebus 中定时检测是否为空
{
    if(smsVec.size() != 0)//为空
        return true;
    else
    {
        return false;
    }
}*/
void DataFactory::initSomeValues()
{
    exitFlag = false; //thread exited ?
    useNet = false;
    netState = NET_NO_START;
    netCheckCount = 0;//net check count
    uartState = UART_NO_START;
    uartTryCnt = 3;
    sqlState = SQL_NO_START;
    //sqlTryCnt  = 2;
    isOnline = false;//未检测到在线
    //oldTime = -1;
    smsNums = 0;//短消息计数
}

bool DataFactory::isOk(QString& str)
{
    if(str.contains("OK"))
    {
        timeBus.setFistCheckSim(true);//已经检查
        isOnline = true;
        return true;
    }

    return false;
}//
bool DataFactory::isOk(QByteArray& str)
{
    if(str.contains("OK"))
    {
        timeBus.setFistCheckSim(true);//已经检查
        isOnline = true;
        return true;
    }
    return false;
}//QByteArray

void DataFactory::onSerialReadyRead()
{
    if(serialPort->bytesAvailable() >= 2)
    {
        // QByteArray qbyte = serialPort->readAll();
        while(1)
        {
            QByteArray qbyte;          
            {
				//读取一行数据
                qbyte = serialPort->readLine();
                //qDebug() <<"Data>>>>>"<< qbyte.data();
				//数据为空则退出
                if(qbyte.size() == 0)
                    break;
				//收到短消息到来命令
                if(qbyte.contains("CMTI"))
                {
                    QByteArray q = qbyte.trimmed();
					//提取最后的短消息编号
                    int index = q.indexOf(',');
                    index = q.size() - index;                  
                    index = q.right(index - 1).toInt();
                    if(index != 0)
                    {
						//发送读取短消息命令
                        sendMsgReadN(index);
                        //QTimer::singleShot(10 * 1000, this, SLOT(sendMsgReadN(index)));
                    }
                    return;
                }
				//如果为数据行
                else if(qbyte.contains('Z') )
                {
					//数据行如果被分成多行发送过来
					if (!qbyte.contains('T') )
					{
						QByteArray tbyte;
						while(!tbyte.contains('T')){
							tbyte=serialPort->readLine();
							//没有收到数据行的结束标志
							if(tbyte.contains("OK")||tbyte.contains("ERROR")){
								return;
							}
							if(tbyte.trimmed().size()>=1)
								qbyte=qbyte.trimmed()+tbyte.trimmed();
						}					
					}
					//短消息数增加
                    smsNums++;

					qbyte = qbyte.trimmed();
                    //qDebug() << "OK:" << qbyte << "   " << qbyte.size() << endl;
					//将有效数据放入循环队列
                    mutex.lock();
                    circularQueue.push_back('P');
                    circularQueue.push_n_back(qbyte.data(), qbyte.size());
                    circularQueue.push_back('Q');
                    mutex.unlock();
					//唤醒处理线程
                    bufferIsEmpty.wakeAll();
					//消息太多，删除
                    if(smsNums >= 20)
                    {
                        QTimer::singleShot(10 * 1000, this, SLOT(sendMsgRMALL()));
						smsNums=0;
                    }
                }
                else
                {
                    if(isOk(qbyte))
                    {
                        //qDebug() << "Contain OK" << endl;
                    }
                }
            }
        }
    }
}

void DataFactory::onNetReadyRead()
{
    if(tcpSocket->bytesAvailable() >= 2)
    {
        //if(mutex.tryLock())
        {
            mutex.lock();
            QByteArray qbyte = tcpSocket->readAll();
            circularQueue.push_back('P');
            circularQueue.push_n_back(qbyte.data(), qbyte.size());
            circularQueue.push_back('Q');
            mutex.unlock();
            bufferIsEmpty.wakeAll();
        }
    }
}
void DataFactory::checkNetWhenUseNet()
{
    if(useNet)
    {
        ++netCheckCount;

        if(netCheckCount == 300) //5 mints
        {
            netCheckCount = 0;

            if(netState == NET_DISCONNECTED)
            {
                resetConnectToServer();
            }
        }
    }
}
void DataFactory::resetConnectToServer()
{
    useNet = true;
    tcpSocket->close();
    netState = NET_DISCONNECTED;
    connectToServer(serverIp, serverPort);
    netState = NET_CONNECTING;
}
void DataFactory::shutDownConnect()
{
    useNet = false;
    tcpSocket->close();
    netState = NET_DISCONNECTED;
}
void DataFactory::connectToServer(QString & addr, quint16 port)
{
    useNet = true;
    serverIp = addr;
    serverPort = port;
    netState = NET_CONNECTING;
    tcpSocket->connectToHost(addr, port);
    //status signal receive by mainwindow
}
void DataFactory::dontUseNet()
{
    useNet = false;

    if(netState != NET_DISCONNECTED)
        tcpSocket->close();

    netState = NET_DISCONNECTED;
    delete tcpSocket;
    tcpSocket = NULL;
}
DataFactory::~DataFactory()
{
    exitFlag = true;
    bufferIsEmpty.wakeAll();
    waitThread();
    exit(0);
}

//在数据中提取传感器编号A-10  B-11
int DataFactory::getNodeIndex(char ch)
{
    if(ch <= '9')
    {
        return (ch - '0');
    }
    else if(ch <= 'Z')
    {
        return (ch - 'A' + 10);
    }
    else if(ch <= 'x')
    {
        return (ch - 'a' + 10);
    }
    return -1;
}
//提取数据中描述节点出错的信息
int DataFactory::getNodeErrorType(char ch1, char ch2)
{
    if(ch1 == 'C')
    {
        return CF;
    }
    else if(ch1 == 'R')
        return RF;
    else if(ch1 == 'S')
    {
        if(ch2 == 'F')
            return SF;
        else if(ch2 == 'W')
            return SW;
    }

    return UnKnowError;
}

void DataFactory::enSQL(int type, int stationNums, int sensorNo, float data)
{ 
    if((!getSQLState())||((data >=-5)&&data<5))
    {
        return;
    }

    //qDebug()<<"stationNums:"<<sensorNo<<"type:"<<type<<"  Data:"<<data<<endl;
    //void asyncInsertData(const QString& _table,const QString& t, uint id, int stationNo, int sensorNo, float _data);
    long nowTime = 0;//timeBus.getTimeBusCnt();
    QDateTime time = QDateTime::currentDateTime();
    QString str = time.toString("yyyy-MM-dd hh:mm:ss");
    switch(type)
    {
        /*!
          * 以下为将数据分发到各个波形显示模块，而且使用异步方式插入到数据库中
          */
        case DATA_G:
            {
                sqlthread->asyncInsertData(SQL_G , str, nowTime, stationNums, sensorNo, data);
                break;
            }

        case DATA_Y:
            {
                sqlthread->asyncInsertData(SQL_Y , str, nowTime,  stationNums, sensorNo, data);
                break;
            }

        case DATA_V:
            {
                sqlthread->asyncInsertData(SQL_V , str, nowTime,  stationNums, sensorNo, data);
                break;
            }

        default:
            break;
    }
}
//0.000012078
//connect(&render,SIGNAL(notify(int)),this,SLOT(OnNotify(int)));
void DataFactory::slove(char* str, int len)
{
    str[len] = '\0';
    //qDebug() << str << endl;
    int index = 0;
    int node = 0;
    float data;
	//float resData;
    char tmp[5];
    int no;
    int station = str[index++] - '1'; //采集站编号(本身从1开始，代码中转换成从0开始)
    no = 0;//传感器编号
	double coeff = 0.0004026*30*700*900;
	double dist;
	//double k = 0.0004026;

    while(1)
    {
        if(no >= 14) no = 0;

        if(str[index] == 'G')
        {
            no = 0;//重新计数
            index++;

            // qDebug() << "This is G" << endl;
            while(1)
            {
                if(index == len)
                {
                    return;
                }

                if(str[index] == 'X') //错误
                {
                    index++;
                    node = getNodeIndex(str[index++]);
                    data = getNodeErrorType(str[index++], str[index++]);
                    //no++;
                }
                else if((str[index] == 'G') || (str[index] == 'Y') || (str[index] == 'V'))
                {
                    break;
                }
                else  //数据
                {
                    memcpy(tmp, str + index, 4);
                    tmp[4] = '\0';
                    data   =   strtol(tmp, NULL, 16);
                    //no++;
                    index += 4;
                    //qDebug()<<"Str is:"<<tmp<<endl;
                }
				if(data >0){
					data = (double)data/10.0;
					dist = 2190*2190 - data*data;
					data = coeff * dist;
				}
                enSQL(DATA_G, station, no, data);
                //qDebug()<<"Station:"<<station<<"  DATAG, No:"<<no<<"  Data:"<<data<<endl;
                emit sendRemoteDataToMaiwindow(station, DATA_G, no++, data);//not node
            }
        }
        else if(str[index] == 'Y')
        {
            index++;
            no = 4;//应力计从4开始编号
            //qDebug() << "This is Y" << endl;

            while(1)
            {
                if(index == len)
                {
                    return;
                }

                if(str[index] == 'X') //错误
                {
                    index++;
                    node = getNodeIndex(str[index++]);
                    data = getNodeErrorType(str[index++], str[index++]);
                    //no++;
                }
                else if((str[index] == 'G') || (str[index] == 'Y') || (str[index] == 'V'))
                {
                    break;
                }
                else  //数据
                {
                    memcpy(tmp, str + index, 4);
                    tmp[4] = '\0';
                    data   =   strtol(tmp, NULL, 16);
                    //no++;
                    index += 4;
                }
				if(data >0){
					//double coeff = 0.0004026*30*700*900;
					qDebug()<<"data="<<data<<endl;
					data = (double)data/10.0;
					dist = 2190*2190 - data*data;
					data = coeff * dist*(0.000001);
					qDebug()<<"dataEnd="<<data<<endl;
				}
                enSQL(DATA_Y, station, no, data);
                emit sendRemoteDataToMaiwindow(station, DATA_Y, no++, data);
                //qDebug()<<"Station:"<<station<<"  DATAY, No:"<<no<<"  Data:"<<data<<endl;
            }
        }
        else if(str[index] == 'V')
        {
            index++;
            no = 13;

            //qDebug() << "This is V" << endl;
            if((str[index] == 'G') || (str[index] == 'Y') || (str[index] == 'V'))
            {
                continue;
            }

            memcpy(tmp, str + index, 3);
            tmp[3] = '\0';
            data   =   strtol(tmp, NULL, 16);
            index += 3;
			
            enSQL(DATA_V, station, no, data/10.0);
            emit sendRemoteDataToMaiwindow(station, VOLTAGE, no, data/10.0);
        }
        else
        {
            break;
        }
    }
}
void DataFactory::run()
{
    bool bstart = false;
    int cnt = 0;
    char tmp[200];
    char buff[2];
    int len;
    //long oldTime = -1;
    long nowTime;
    float data ;

    while(true)
    {
        mutex.lock();

        while(circularQueue.size() <= 2)
        {
            bufferIsEmpty.wait(&mutex);

            if(exitFlag)
            {
                mutex.unlock();
                return;
            }
        }

        if(!bstart)
        {
            while(true)
            {
                if(circularQueue.size() < 2) break;//continue;

                circularQueue.get_n_front(buff, 2);

                if((buff[0] == 'P') && (buff[1] == 'Z'))
                {
                    bstart = true;
                    cnt = 0;
                    circularQueue.remove_n_front(2);
                    len = circularQueue.front();
                    break;
                }
                else
                {
                    circularQueue.remove_n_front(1);
                }
            }
        }
        else
        {
            while(true)
            {
                if(circularQueue.size() < 2) break;

                circularQueue.get_n_front(buff, 2);

                if((buff[0] == 'T') && (buff[1] == 'Q'))
                {
                    slove(tmp, cnt);
                   // qDebug() << QString::fromWCharArray(L"收到一个完整的数据帧:") << cnt << endl;
                    /*
                    for(int ll = 0; ll < cnt; ll++)
                    {
                        qDebug() << tmp[ll] << endl;
                    }*/
                    bstart = false;
                    cnt = 0;
                    circularQueue.remove_n_front(2);
                    break;
                }
                else
                {
                    circularQueue.remove_n_front(1);
                    tmp[cnt++] = buff[0];

                    //qDebug()<<"Data:"<<buff[0]<<endl;

					//TX  QX  XT XQ XX (这些情况说明数据必然有错误)
                    if((cnt >= 150)||(buff[0] == 'T')||(buff[0] == 'Q'))
                    {
						//qDebug()<<"Error,MAXSIZE  "<<buff[0]<<"  "<<buff[1]<<"  "<<cnt<<endl;
                        bstart = false;
                        cnt = 0;
                    }
                }
            }
        }

        mutex.unlock();
    }
}
bool DataFactory::shutDownSQLConnect()
{
    //
    sqlState = SQL_DISCONNECTED;
    return true;
}
bool DataFactory::shutDownSerial()
{
    serialPort->close();
    uartState = UART_CLOSED;
    return true;
}
void DataFactory::waitThread()
{
    // ok call
    wait();
}